#include "qfrozentreewidget.h"
#include <QApplication>
#include <QDebug>
#include <QDialog>
#include <QGraphicsDropShadowEffect>
#include <QHeaderView>
#include <QLabel>
#include <QScrollBar>
#include <QTime>

class MyQWidget : public QDialog //exec
{
    //    Q_OBJECT
    QLabel m_lable;
    QPoint dragPosition; //鼠标拖动的位置
    enum
    {
        nodir,
        right = 0x08,
    } resizeDir; //更改尺寸的方向
public:
    MyQWidget(QWidget *parent = 0)
    {
        this->setParent(parent);
        this->setFocus();
        resizeDir = nodir; //初始化检测方向为无
        setMouseTracking(true); //开启鼠标追踪
        m_lable.setParent(this);
        this->setObjectName("WW");
        this->setStyleSheet("#WW{"
                            "background-color:rgba(100,20,20, 80);"
                            "border-style: solid;"
                            "border-width: 2px;"
                            "border-top-color: transparent;"
                            "border-left-color: transparent;"
                            "border-right-color: #D03F0A;"
                            "border-bottom-color:transparent; "
                            "}");
    }
    ~MyQWidget()
    {
    }
    QSize m_size;

#define EDGE_MARGIN 8

    QPoint m_startPos;
    QDate m_startDate;
    int m_dayW;
    void textInit(QDate startDate, int days, int dayW)
    {
        m_lable.resize(this->size().width() - EDGE_MARGIN, this->size().height());
        m_startDate = startDate;
        m_dayW = dayW;

        QString txt;
        txt.append(startDate.toString("M-d"));
        txt.append("|");
        txt.append(QString::number(days));
        m_lable.setText(txt);
        m_lable.setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    }
    void textReset(Qt::Alignment align)
    {
        int offset = (this->pos().x() - m_startPos.x()) / m_dayW;
        if (this->pos().x() < m_startPos.x())
            offset -= 1;

        int days = (this->width() / m_dayW);

        QString txt;
        if (align == Qt::AlignRight)
        {
            if (days <= 0)
                days = 0;
            txt.append(m_startDate.addDays(offset).addDays(days).toString("M-d"));
            txt.append("|");
            txt.append(QString::number(days + 1));
        }
        else
        {
            txt.append(m_startDate.addDays(offset).toString("M-d"));
            txt.append("|");
            txt.append(QString::number(days));
        }

        m_lable.resize(this->size().width() - EDGE_MARGIN, this->size().height());
        m_lable.setText(txt);
        m_lable.setAlignment(align | Qt::AlignVCenter);
    }

private:
    void testEdge(QMouseEvent *event)
    {
        //计算鼠标距离窗口上下左右有多少距离
        //        int diffLeft = event->globalPos().x() - frameGeometry().left();
        //        int diffRight = event->globalPos().x() - frameGeometry().right();
        //        int diffTop = event->globalPos().y() - frameGeometry().top();
        //        int diffBottom = event->globalPos().y() - frameGeometry().bottom();
        int diffRight = this->width() - event->pos().x();

        //        qDebug() << event->pos().x() << diffLeft << diffRight;
        Qt::CursorShape cursorShape;
        //根据 边缘距离 分类改变尺寸的方向
        if (abs(diffRight) < EDGE_MARGIN)
        {
            resizeDir = right;
            cursorShape = Qt::SizeHorCursor;
        }
        else
        {
            resizeDir = nodir;
            cursorShape = Qt::PointingHandCursor;
        }

        QApplication::setOverrideCursor(cursorShape);
    }

protected:
    virtual void mousePressEvent(QMouseEvent *event) override
    {
        if (event->button() == Qt::LeftButton) //每当按下鼠标左键就记录一下位置
        {
            m_startPos = this->pos();
            dragPosition = event->globalPos() - frameGeometry().topLeft(); //获得鼠标按键位置相对窗口左上面的位置
            // qDebug() << dragPosition;
        }
    }
    virtual void leaveEvent(QEvent *event) override
    {
        resizeDir = nodir;
        QApplication::setOverrideCursor(Qt::CustomCursor);
        this->close();
        QWidget::leaveEvent(event);
    }
    virtual void enterEvent(QEvent *event) override
    {
        QWidget::enterEvent(event);
    }
    virtual void mouseReleaseEvent(QMouseEvent *event) override
    {
        qDebug() << "mouseReleaseEvent";
        resizeDir = nodir;
        QApplication::setOverrideCursor(Qt::CustomCursor);
        this->close();
    }
    virtual void mouseMoveEvent(QMouseEvent *event) override
    {
        //如果左键是按下的
        if (event->buttons() & Qt::LeftButton)
        {
            //如果鼠标不是放在边缘那么说明这是在拖动窗口
            if (resizeDir == nodir)
            {
                QPoint pt = event->globalPos() - dragPosition;
                // move(pt);
                move(pt.x(), this->pos().y()); //只左右移动
                textReset(Qt::AlignLeft);
            }
            else
            {
                //检测右分量
                if (resizeDir & right)
                {
                    this->resize(event->pos().x(), this->size().height());
                    textReset(Qt::AlignRight);
                    return;
                }
            }
        }
        else
            testEdge(event); //当不拖动窗口、不改变窗口大小尺寸的时候  检测鼠标边缘
    }
};

QFrozenTreeWidget::QFrozenTreeWidget(QWidget *parent)
    : QTreeWidget(parent)
{
    //创建树
    m_frontTreeWidget = new QTreeWidget(this);
    m_frontTreeWidget->setObjectName("tf");
    m_backTreeWidget->setObjectName("tb");

    //让树覆盖在上层
    m_frontTreeWidget->viewport()->stackUnder(this);
    //前置树关闭滚动条，由后置树本滚动条控制
    m_frontTreeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    m_frontTreeWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    //设置前置树颜色
    m_frontTreeWidget->setStyleSheet("QTreeView{border:none; background-color:#F9F9F9;}"
                                     "QHeaderView::section{padding-left:5px;border:1px solid #E0E0E0; background-color:#F0F0F0;}");
    this->setStyleSheet("QTreeView{border:none;}"
                        "QTreeWidget::item{height:32px;}"
                        "QHeaderView::section{padding-left:5px;border:1px solid #E0E0E0; background-color:#F0F0F0;}"
                        "QToolTip{border-radius:2px;border:1px solid rgb(118, 118, 118); background-color:rgba(255, 255, 255, 1); color:#484848; }"); /*font-size:13px;*/

    //前树边界阴影
    QGraphicsDropShadowEffect *ef = new QGraphicsDropShadowEffect;
    ef->setOffset(2, 1);
    ef->setColor(QColor(0, 0, 0, 50));
    ef->setBlurRadius(30);
    m_frontTreeWidget->setGraphicsEffect(ef);


    //后置树不获得焦点
    m_backTreeWidget->setFocusPolicy(Qt::NoFocus);

    //让固定列宽度不能手动调整大小，而跟随本树第一列大小来改变
    m_backTreeWidget->header()->setSectionResizeMode(QHeaderView::Fixed);

    //    //设置选择模式一样
    //    m_frontTreeWidget->setSelectionModel(selectionModel());

    //设置滚动条模式按像素为单位滚动
    m_backTreeWidget->setHorizontalScrollMode(ScrollPerPixel);
    m_backTreeWidget->setVerticalScrollMode(ScrollPerPixel);
    m_frontTreeWidget->setVerticalScrollMode(ScrollPerPixel);
    //设置后置树不能双击选中
    m_frontTreeWidget->setExpandsOnDoubleClick(false);
    m_backTreeWidget->setExpandsOnDoubleClick(false);

    qDebug() << m_frontTreeWidget->objectName() << m_backTreeWidget->objectName();
    //前置树选中行改变同步到后树
    connect(m_frontTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem *)), this, SLOT(onCurrentItemChangedb(QTreeWidgetItem*,QTreeWidgetItem *)));
    connect(m_backTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem *)), this, SLOT(onCurrentItemChangedf(QTreeWidgetItem*,QTreeWidgetItem *)));
    //表头调节大小同步
    connect(m_backTreeWidget->header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(UpdateSectionWidthSlot(int,int,int)));
    connect(m_frontTreeWidget->header(), SIGNAL(sectionResized(int,int,int)), this, SLOT(UpdateSectionWidthSlotb(int,int,int)));
    //前后置树的垂直滚动条同步滚动
    connect(m_frontTreeWidget->verticalScrollBar(), SIGNAL(valueChanged(int)), m_backTreeWidget->verticalScrollBar(), SLOT(setValue(int)));
    connect(m_backTreeWidget->verticalScrollBar(), SIGNAL(valueChanged(int)), m_frontTreeWidget->verticalScrollBar(), SLOT(setValue(int)));
    connect(m_backTreeWidget->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(hSetValue(int)));

    //前置树展合同步到后树
    connect(m_frontTreeWidget, SIGNAL(itemCollapsed(QTreeWidgetItem*)), this, SLOT(OnItemCollapsed(QTreeWidgetItem*)));
    connect(m_frontTreeWidget, SIGNAL(itemExpanded(QTreeWidgetItem*)), this, SLOT(OnItemExpanded(QTreeWidgetItem*)));
    //后置树展合同步到前树
    connect(this, SIGNAL(itemCollapsed(QTreeWidgetItem *)), this, SLOT(OnItemCollapsedf(QTreeWidgetItem *)));
    connect(this, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(OnItemExpandedf(QTreeWidgetItem *)));
    //第一列item勾选
    connect(m_frontTreeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(OnItemChanged(QTreeWidgetItem*,int)));
    m_frontTreeWidget->show();
}

QFrozenTreeWidget::~QFrozenTreeWidget()
{
}
void QFrozenTreeWidget::SetMomlable(QLabel *l)
{
    m_l = l;
}
void QFrozenTreeWidget::hSetValue(int val)
{
    if (m_l)
    {
        int dateColumnW = 38;
        int column = val / dateColumnW + m_frontTreeWidget->columnCount();
        QDate onDate = QDate::fromString(m_back_lables.at(column), "yyyyMMdd");
        m_l->setText(onDate.toString("yyyy年MM月"));
    }
}
//void QFrozenTreeWidget::drawRow(QPainter *painter,
//    const QStyleOptionViewItem &options,
//    const QModelIndex &index) const
//{
//    QStyleOptionViewItem opt(options);
//    opt.rect.adjust(0, 5, 0, -5);
//    QTreeWidget::drawRow(painter, opt, index);
//}
void QFrozenTreeWidget::resizeEvent(QResizeEvent *event)
{
    QTreeWidget::resizeEvent(event);
    UpdateFrozenTreeGeometry();
}
QModelIndex QFrozenTreeWidget::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
{
    QModelIndex current = QTreeWidget::moveCursor(cursorAction, modifiers);
    qDebug() << cursorAction;
    if (cursorAction == MoveLeft && current.column() > 0
            && visualRect(current).topLeft().x() < m_frontTreeWidget->columnWidth(0))
    {
        const int newValue = horizontalScrollBar()->value() + visualRect(current).topLeft().x()
                - m_frontTreeWidget->columnWidth(0);
        horizontalScrollBar()->setValue(newValue);
    }
    return current;
}
void QFrozenTreeWidget::scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint)
{
    if (index.column() > 0)
    {
        QTreeWidget::scrollTo(index, hint);
    }
}

QTreeWidgetItem *QFrozenTreeWidget::GetItemFromIndex(QTreeWidgetItem *item, structIndex *index)
{
    if (index->m_index == -1)
    {
        return item;
    }
    QTreeWidgetItem *targetItem = GetItemFromIndex(item->child(index->m_index), index->m_pChildIndex);
    if (index->m_pChildIndex != NULL)
    {
        delete index->m_pChildIndex;
        index->m_pChildIndex = NULL;
    }
    return targetItem;
}
//浮动列总宽
int QFrozenTreeWidget::getFrontTreeWidth()
{
    int w = 0;
    for (int i = 0; i < m_frontTreeWidget->columnCount(); i++)
        w += columnWidth(i);
    return w;
}
void QFrozenTreeWidget::UpdateFrozenTreeGeometry()
{
    int w = getFrontTreeWidth();
    m_frontTreeWidget->setGeometry(frameWidth(), frameWidth(),
        w, viewport()->height() + header()->height());
}
structIndex *QFrozenTreeWidget::GetItemIndex(QTreeWidgetItem *targetItem, QTreeWidgetItem *sourceItem)
{
    if (targetItem == sourceItem)
    {
        return new structIndex;
    }
    for (int i = 0; i < targetItem->childCount(); ++i)
    {
        structIndex *pChildStructIndex = GetItemIndex(targetItem->child(i), sourceItem);
        if (pChildStructIndex != NULL)
        {
            structIndex *pStructIndex = new structIndex;
            pStructIndex->m_pChildIndex = pChildStructIndex;
            pStructIndex->m_index = i;
            return pStructIndex;
        }
    }
    return NULL;
}
QTreeWidgetItem *QFrozenTreeWidget::GetItemFromItem(QTreeWidget *targetTree, QTreeWidgetItem *souceItem)
{
    structIndex *pStructIndex = GetItemIndex(souceItem->treeWidget()->invisibleRootItem(), souceItem);
    QTreeWidgetItem *item = GetItemFromIndex(targetTree->invisibleRootItem(), pStructIndex);
    delete pStructIndex;
    return item;
}

QTreeWidget *QFrozenTreeWidget::getUpperTree()
{
    return m_frontTreeWidget;
}
QTreeWidget *QFrozenTreeWidget::getLowerTree()
{
    return m_backTreeWidget;
}

QTreeWidgetItem *QFrozenTreeWidget::getUpperItem(QTreeWidgetItem *item)
{
    if (item->treeWidget()->objectName() == "tf")
        return item;
    else
        return GetItemFromItem(m_frontTreeWidget, item);
}
QTreeWidgetItem *QFrozenTreeWidget::getLowerItem(QTreeWidgetItem *item)
{
    if (item->treeWidget()->objectName() == "tb")
        return item;
    else
        return GetItemFromItem(m_backTreeWidget, item);
}

void QFrozenTreeWidget::SetParentCheckState(QTreeWidgetItem *parentItem)
{
    if (parentItem == NULL)
    {
        return;
    }
    int count = 0;
    for (int i = 0; i < parentItem->childCount(); ++i)
    {
        if (parentItem->child(i)->checkState(0) == Qt::Checked)
        {
            count++;
        }
    }
    if (count == parentItem->childCount())
    {
        //        parentItem->setCheckState(0, Qt::Checked);
    }
    else
    {
        parentItem->setCheckState(0, Qt::Unchecked);
    }
    GetItemFromItem(this, parentItem)->setCheckState(0, parentItem->checkState(0));
    SetParentCheckState(parentItem->parent());
}
void QFrozenTreeWidget::SetChildCheckState(QTreeWidgetItem *selfItem)
{
    for (int i = 0; i < selfItem->childCount(); ++i)
    {
        selfItem->child(i)->setCheckState(0, selfItem->checkState(0));
        GetItemFromItem(this, selfItem->child(i))->setCheckState(0, selfItem->checkState(0));
        SetChildCheckState(selfItem->child(i));
    }
}
void QFrozenTreeWidget::SetItemChecked(QTreeWidgetItem *item)
{
    QTreeWidgetItem *targetItem = GetItemFromItem(m_frontTreeWidget, item);
    targetItem->setCheckState(0, item->checkState(0));
}

bool QFrozenTreeWidget::setDateColumn(QTreeWidgetItem *backitem, int column, int &newstartdate, int &newstopdate)
{
    //检查双击是否在时间条中
    int date = this->getHeadtxt(column).toInt();
    int startdate = backitem->text(m_startColumn).toInt();
    int stopdate = backitem->text(m_stopColumn).toInt();
    if (date < startdate || date > stopdate)
        return false;

    this->setItemWidget(backitem, column, new QLabel);

    //滑动条参数
    QPoint pos;
    QSize size;

    //通过当前位置创建一个Widget来确认滑动条的大小
    QWidget *p = backitem->treeWidget()->itemWidget(backitem, column);
    pos = p->pos();
    size = p->size();
    this->removeItemWidget(backitem, column);
    qDebug() << size;

    QDate startDate = QDate::fromString(QString::number(startdate), "yyyyMMdd");
    QDate stopDate = QDate::fromString(QString::number(stopdate), "yyyyMMdd");
    QDate onDate = QDate::fromString(m_back_lables.at(column), "yyyyMMdd");

    int days = startDate.daysTo(stopDate) + 1; //周期包含几天
    int predays = startDate.daysTo(onDate); //点击前面有几天
    int dayW = size.width(); //一天的宽度

    //移动到起始位置
    pos.setX(pos.x() - (size.width() * predays));
    pos.setY(pos.y() + this->header()->height());

    MyQWidget *m_dateswidget = new MyQWidget(this);
    m_dateswidget->move(pos);

    //重置大小
    size.setWidth(dayW * days);
    m_dateswidget->resize(size);
    m_dateswidget->textInit(startDate, days, dayW);

    //设置层级和样式
    m_dateswidget->stackUnder(m_frontTreeWidget);

    //等待操作退出
    m_dateswidget->exec();

    //计算时间偏移
    int offsetDate;
    if (m_dateswidget->pos().x() > pos.x()) //后移
    {
        offsetDate = (m_dateswidget->pos().x() - pos.x()) / dayW;
    }
    else //前移
    {
        offsetDate = (pos.x() - m_dateswidget->pos().x()) / dayW
            + (((pos.x() - m_dateswidget->pos().x()) % dayW) == 0 ? 0 : 1);
        offsetDate = -offsetDate;
    }

    //计算天数
    if (size.width() != m_dateswidget->size().width())
    {
        days = m_dateswidget->size().width() / dayW
            + ((m_dateswidget->size().width() % dayW) == 0 ? 0 : 1);
        if (days == 0)
            days = 1;
    }
    delete m_dateswidget;
    qDebug() << "offsetDate:" << offsetDate << "| day:" << days;

    //换算成新时间
    startDate = QDate::fromString(QString::number(startdate), "yyyyMMdd");
    startDate = startDate.addDays(offsetDate);
    stopDate = startDate.addDays(days - 1);
    newstartdate = startDate.toString("yyyyMMdd").toInt();
    newstopdate = stopDate.toString("yyyyMMdd").toInt();

    if (startdate != newstartdate || stopdate != newstopdate)
    {
        return true;
    }

    return false;
}

void QFrozenTreeWidget::setColumnHidden1(int column, bool hidden)
{
    m_frontTreeWidget->setColumnWidth(column, 150);
    this->setColumnHidden(column, hidden);
    m_frontTreeWidget->setColumnHidden(column, hidden);
}
void QFrozenTreeWidget::setHidden1(QTreeWidgetItem *itemb, bool hidden)
{
    getUpperItem(itemb)->setHidden(hidden);
    getLowerItem(itemb)->setHidden(hidden);
}

//设置表头
void QFrozenTreeWidget::setColumnHeader(
    const QStringList &labels, //自定义列表头
    int frozenColumn, //指定前几列浮动
    int startColumn, //指定周期开始日期列
    int stopColumn, //指定周期结束日期列
    int starttime, //绘制日期起始值
    int stoptime) //绘制日期结束值
{
    m_startColumn = startColumn;
    m_stopColumn = stopColumn;

    disconnect(m_frontTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(onCurrentItemChangedb(QTreeWidgetItem *, QTreeWidgetItem *)));
    disconnect(m_backTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(onCurrentItemChangedf(QTreeWidgetItem *, QTreeWidgetItem *)));
    m_frontTreeWidget->clear();
    this->clear();
    connect(m_frontTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(onCurrentItemChangedb(QTreeWidgetItem *, QTreeWidgetItem *)));
    connect(m_backTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(onCurrentItemChangedf(QTreeWidgetItem *, QTreeWidgetItem *)));

    //前景树列表头，frozenColumn=0时全部复制
    QStringList frozenlabls;
    if (frozenColumn == 0)
        frozenlabls = labels;
    else
        for (int i = 0; i < frozenColumn; i++)
            frozenlabls.append(labels.at(i));
    m_frontTreeWidget->setColumnCount(frozenlabls.length());
    m_frontTreeWidget->setHeaderLabels(frozenlabls);

    //    qDebug() << frozenColumn << frozenlabls.length() << frozenlabls;

    //背景树列表头，除指定头外添加时间
    m_back_lables = labels;
    if (starttime != 0 && stoptime != 0 && stoptime > starttime)
    {
        //设置后树表头（除月首显示完整值其余显示缩略值）
        QDate d1 = QDate::fromString(QString::number(starttime), "yyyyMMdd");
        QDate d2 = QDate::fromString(QString::number(stoptime), "yyyyMMdd");
        while (d1 <= d2)
        {
            //            if (d1.toString("dd").toInt() == 1)
            //                m_back_lables.append(d1.toString("yyyyMMdd"));
            //            else
            m_back_lables.append(d1.toString("d"));
            d1 = d1.addDays(1);
        }
        m_backTreeWidget->setColumnCount(m_back_lables.length());
        m_backTreeWidget->setHeaderLabels(m_back_lables);

        //设置表头列宽度
        for (int i = labels.length(); i < m_back_lables.length(); i++)
        {
            if (m_back_lables.at(i).length() <= 2) //不是月份
                m_backTreeWidget->setColumnWidth(i, 20);
            else
                m_backTreeWidget->setColumnWidth(i, 100);
        }

        //记录完整数值表头，用于根据时间查找所在列
        m_back_lables = labels;
        d1 = QDate::fromString(QString::number(starttime), "yyyyMMdd");
        while (d1 <= d2)
        {
            m_back_lables.append(d1.toString("yyyyMMdd"));
            d1 = d1.addDays(1);
        }
        qDebug() << "head len:" << m_back_lables.length();
        qDebug() << getFrontTreeWidth()
                 << (m_back_lables.length() - labels.length()) * (20 + 2);
        qDebug() << m_backTreeWidget->width();
    }
    else
    {
        m_backTreeWidget->setColumnCount(m_back_lables.length());
        m_backTreeWidget->setHeaderLabels(m_back_lables);
    }
}

//同步改变项文本
void QFrozenTreeWidget::changedText(QTreeWidgetItem *item, int column, const QString &txt)
{
    if (column < m_frontTreeWidget->columnCount())
        getUpperItem(item)->setText(column, txt);
    getLowerItem(item)->setText(column, txt);
}

void QFrozenTreeWidget::changedTimes(QTreeWidgetItem *item, int starttime, int stoptime, QColor color, int progress)
{
    int oldstartdate = item->text(m_startColumn).toInt();
    int oldstopdate = item->text(m_stopColumn).toInt();
    setExecutionTime(getLowerItem(item), oldstartdate, oldstopdate, Qt::white, 100);

    setExecutionTime(getLowerItem(item), starttime, stoptime, color, progress);
    changedText(item, m_startColumn, QString::number(starttime));
    changedText(item, m_stopColumn, QString::number(stoptime));
}

void QFrozenTreeWidget::setExecutionTime(QTreeWidgetItem *item, int starttime, int stoptime, QColor color, int progress)
{
    if (starttime != 0 && stoptime != 0 && stoptime >= starttime)
    {
        int column, days;
        QDate d1 = QDate::fromString(QString::number(starttime), "yyyyMMdd");
        QDate d2 = QDate::fromString(QString::number(stoptime), "yyyyMMdd");
        days = d1.daysTo(d2) + 1;
        QString tip = QString(" %1(%2~%3), %4% ")
                          .arg(days)
                          .arg(d1.toString("M.d"))
                          .arg(d2.toString("M.d"))
                          .arg(progress);

        progress = days * progress / 100;
        column = m_back_lables.indexOf(QString::number(starttime));
        for (int i = 0; i < days; i++)
        {
            if (i < progress)
                color.setAlpha(120);
            else
                color.setAlpha(112);

            QLinearGradient linearGradient(0, 0, 0, 32); //初始化线条画刷，宽度2
            linearGradient.setColorAt(0, Qt::white); //上边颜色
            linearGradient.setColorAt(0.1, Qt::white); //上边颜色
            linearGradient.setColorAt(0.11, color); //下边颜色
            linearGradient.setColorAt(0.9, color); //下边颜色
            linearGradient.setColorAt(0.91, Qt::white); //上边颜色
            linearGradient.setColorAt(1, Qt::white); //上边颜色

            item->setBackground(column, QBrush(linearGradient));
            item->setToolTip(column, tip);
            column++;
        }
    }

    //周1边界颜色
    int start = m_frontTreeWidget->columnCount();
    QDate date = QDate::fromString(m_back_lables.at(start), "yyyyMMdd");
    while (date.dayOfWeek() != Qt::Monday)
    {
        date = date.addDays(1);
        start++;
    }
    for (int i = start; i < m_backTreeWidget->columnCount(); i += 7)
    {
        if (m_back_lables.at(i).toInt() < starttime
            || m_back_lables.at(i).toInt() > stoptime)
        {
            QLinearGradient linearGradient(1, 1, 2, 1); //初始化线条画刷，宽度2
            linearGradient.setColorAt(0, Qt::lightGray); //左边颜色
            linearGradient.setColorAt(1, Qt::white); //右边颜色
            item->setBackground(i, QBrush(linearGradient));
        }
    }

    //今天边界
    QString currentDate = QDate::currentDate().toString("yyyyMMdd");
    if (currentDate.toInt() < starttime || currentDate.toInt() > stoptime)
    {
        int curColumn = m_back_lables.indexOf(QDate::currentDate().toString("yyyyMMdd"));
        item->setBackground(curColumn, QBrush(QColor(245, 248, 248)));
    }
}
QString QFrozenTreeWidget::getHeadtxt(int column)
{
    return m_back_lables.at(column);
}

QTreeWidgetItem *QFrozenTreeWidget::createTopItem(QStringList lables, int starttime, int stoptime, QColor color, int progress)
{
    QTreeWidgetItem *parent = new QTreeWidgetItem(this->invisibleRootItem(),
        lables);
    QTreeWidgetItem *frontItem = new QTreeWidgetItem(GetItemFromItem(m_frontTreeWidget, m_frontTreeWidget->invisibleRootItem()));

    //把要浮动列的内容从后置项的复制到前置项
    for (int i = 0; i < m_frontTreeWidget->columnCount(); i++)
        frontItem->setText(i, parent->text(i));

    frontItem->setCheckState(0, Qt::Unchecked);
    setExecutionTime(parent, starttime, stoptime, color, progress);
    return parent;
}
QTreeWidgetItem *QFrozenTreeWidget::createChildItem(QTreeWidgetItem *parent, QStringList lables, int starttime, int stoptime, QColor color, int progress)
{
    QTreeWidgetItem *child = new QTreeWidgetItem(parent, lables);
    QTreeWidgetItem *frontItem = new QTreeWidgetItem(GetItemFromItem(m_frontTreeWidget, child->parent()));

    //把要浮动列的内容从后置项的复制到前置项
    for (int i = 0; i < m_frontTreeWidget->columnCount(); i++)
        frontItem->setText(i, child->text(i));

    frontItem->setCheckState(0, Qt::Unchecked);
    setExecutionTime(child, starttime, stoptime, color, progress);
    return child;
}

//前置树展合同步到后置树
void QFrozenTreeWidget::OnItemCollapsed(QTreeWidgetItem *item)
{
    collapseItem(GetItemFromItem(this, item));
}
void QFrozenTreeWidget::OnItemExpanded(QTreeWidgetItem *item)
{
    expandItem(GetItemFromItem(this, item));
}

void QFrozenTreeWidget::OnItemCollapsedf(QTreeWidgetItem *item)
{
    m_frontTreeWidget->collapseItem(GetItemFromItem(m_frontTreeWidget, item));
}
void QFrozenTreeWidget::OnItemExpandedf(QTreeWidgetItem *item)
{
    m_frontTreeWidget->expandItem(GetItemFromItem(m_frontTreeWidget, item));
}

//前后树项选中同步
void QFrozenTreeWidget::onCurrentItemChangedf(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
    (void)previous;
    m_frontTreeWidget->setCurrentItem(GetItemFromItem(m_frontTreeWidget, current));
}
void QFrozenTreeWidget::onCurrentItemChangedb(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
    (void)previous;
    m_backTreeWidget->setCurrentItem(GetItemFromItem(m_backTreeWidget, current));
}

//同步表头宽度，否则后置树能缩到前置内部、前置树最后项接不到后置的下一项
void QFrozenTreeWidget::UpdateSectionWidthSlot(int logicalIndex, int, int newSize)
{
    if (logicalIndex < m_frontTreeWidget->columnCount())
    {
        m_frontTreeWidget->setColumnWidth(logicalIndex, newSize);
        UpdateFrozenTreeGeometry();
    }
}

void QFrozenTreeWidget::UpdateSectionWidthSlotb(int logicalIndex, int, int newSize)
{
    if (logicalIndex < m_frontTreeWidget->columnCount())
    {
        m_backTreeWidget->setColumnWidth(logicalIndex, newSize);
    }
}

//上层同步树的项选择状态到下层
void QFrozenTreeWidget::OnItemChanged(QTreeWidgetItem *item, int column)
{
    getLowerItem(item)->setCheckState(column, item->checkState(column));
    m_frontTreeWidget->blockSignals(true);
    SetChildCheckState(item);
    SetParentCheckState(item->parent());
    m_frontTreeWidget->blockSignals(false);
}

void QFrozenTreeWidget::showAllHidden()
{
    QTreeWidgetItemIterator it(m_backTreeWidget, QTreeWidgetItemIterator::Hidden);
    while (*it)
    {
        setHidden1((*it), false);
        ++it;
    }
}

void QFrozenTreeWidget::getBranchTextByFlags(QStringList &txt, int column, QTreeWidgetItemIterator::IteratorFlags flags)
{
    QTreeWidgetItemIterator it(m_backTreeWidget, flags);
    while (*it)
    {
        //qDebug() << (*it)->text(0);
        txt << (*it)->text(column);
        ++it;
    }
}

void QFrozenTreeWidget::deleteBranchByFlags(QTreeWidgetItemIterator::IteratorFlags flags)
{
    while (1)
    {
        QTreeWidgetItemIterator it(m_backTreeWidget, flags); //重新装载
        if (*it) //不循环单次使用
        {
            deleteBranch(*it);
        }
        else
            break;
    }
}

void QFrozenTreeWidget::deleteBranch(QTreeWidgetItem *item)
{
    //不要直接删除，否则查找依赖被释放会出现错误
    QTreeWidgetItem *item1 = getUpperItem(item);
    QTreeWidgetItem *item2 = getLowerItem(item);
    delete item1;
    delete item2;
}

void QFrozenTreeWidget::getBranchText(QStringList &txt, int column, QTreeWidgetItem *item)
{
    QTreeWidgetItemIterator it(getLowerItem(item));
    while (*it)
    {
        //qDebug() << (*it)->text(0);
        txt << (*it)->text(column);
        ++it;
    }
}
